﻿Imports OMANE.Common
Imports System.ComponentModel
Imports OMANE.Common.UI
Imports Microsoft.Practices.Prism.Commands
Imports System.ComponentModel.Composition

<OMANE.Common.ServiceInfo()> _
<Export(GetType(IUndoRedoService))> _
Public Class UndoRedoServiceImpl
    Implements IUndoRedoService


    Private UndoCommand As New DelegateCommand(Of Object)(AddressOf ExecuteUndoCommand, AddressOf CanExecuteUndoCommand)
    Private RedoCommand As New DelegateCommand(Of Object)(AddressOf ExecuteRedoCommand, AddressOf CanExecuteRedoCommand)
    Private UndoMenuItem As ViewModelMainMenuItem
    Private RedoMenuItem As ViewModelMainMenuItem
    Private UndoTokenStack As New Stack(Of UndoRedoToken)
    Private RedoTokenStack As New Stack(Of UndoRedoToken)


    Public Sub Redo(ByVal context As Object) Implements Common.IUndoRedoService.Redo
        Dim token = RedoTokenStack.Pop()
        UndoTokenStack.Push(token)
        RedoMenuItem.Title = "Retablir : " & _
           If(RedoTokenStack.Count > 0, RedoTokenStack.Peek().Display, "")
        UndoMenuItem.Title = "Annuler : " & token.Display
        token.RedoMethod.Invoke(token.Data)
        UndoCommand.RaiseCanExecuteChanged()
        RedoCommand.RaiseCanExecuteChanged()
    End Sub
    Public Sub Undo(ByVal context As Object) Implements Common.IUndoRedoService.Undo
        Dim token = UndoTokenStack.Pop()
        RedoTokenStack.Push(token)
        UndoMenuItem.Title = "Annuler : " & _
            If(UndoTokenStack.Count > 0, UndoTokenStack.Peek().Display, "")
        RedoMenuItem.Title = "Retablir : " & token.Display
        token.UndoMethod.Invoke(token.Data)
        UndoCommand.RaiseCanExecuteChanged()
        RedoCommand.RaiseCanExecuteChanged()
    End Sub

    Private Sub ExecuteUndoCommand(ByVal parameter As Object)
        'TODO
        ' Undo()
    End Sub
    Private Sub ExecuteRedoCommand(ByVal parameter As Object)
        'TODO
        '  Redo()
    End Sub
    Private Function CanExecuteUndoCommand(ByVal parameter As Object) As Boolean
        Return UndoTokenStack.Count > 0
    End Function
    Private Function CanExecuteRedoCommand(ByVal parameter As Object) As Boolean
        Return RedoTokenStack.Count > 0
    End Function

    Public Sub Initialize() Implements Common.IService.Initialize
        Dim ui = App.Instance.GetService(Of IUIService)()
        UndoMenuItem = New ViewModelMainMenuItem() With {.Title = "Undo", .Command = UndoCommand}
        RedoMenuItem = New ViewModelMainMenuItem() With {.Title = "Redo", .Command = RedoCommand}
        ui.ViewModelMainMenu.Edit.Children.Add(UndoMenuItem)
        ui.ViewModelMainMenu.Edit.Children.Add(RedoMenuItem)
    End Sub

#Region "IDisposable Support"
    Private disposedValue As Boolean ' Pour détecter les appels redondants

    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: supprimez l'état managé (objets managés).
            End If

            ' TODO: libérez les ressources non managées (objets non managés) et substituez la méthode Finalize() ci-dessous.
            ' TODO: définissez les champs volumineux à null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: substituez Finalize() uniquement si Dispose(ByVal disposing As Boolean) ci-dessus comporte du code permettant de libérer des ressources non managées.
    'Protected Overrides Sub Finalize()
    '    ' Ne modifiez pas ce code. Ajoutez du code de nettoyage dans Dispose(ByVal disposing As Boolean) ci-dessus.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' Ce code a été ajouté par Visual Basic pour permettre l'implémentation correcte du modèle pouvant être supprimé.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Ne modifiez pas ce code. Ajoutez du code de nettoyage dans Dispose(ByVal disposing As Boolean) ci-dessus.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

    Public Sub Push(ByVal token As Common.UndoRedoToken) Implements Common.IUndoRedoService.Push
        If Not UndoRedoToken.IsUsable(token) Then Return
        UndoTokenStack.Push(token)
        RedoTokenStack.Clear()
        UndoMenuItem.Title = "Annuler : " & token.Display
        RedoMenuItem.Title = "Retablir"
        UndoCommand.RaiseCanExecuteChanged()
        RedoCommand.RaiseCanExecuteChanged()
    End Sub

  

    Public Sub Push(ByVal context As Object, ByVal token As Common.UndoRedoToken) Implements Common.IUndoRedoService.Push

    End Sub

    Public Sub Redo(ByVal context As Object, ByVal actionCount As Integer) Implements Common.IUndoRedoService.Redo

    End Sub

    Public Sub Undo(ByVal context As Object, ByVal actionCount As Integer) Implements Common.IUndoRedoService.Undo

    End Sub
End Class
